home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-11
/
rlib.zip
/
RLIB.DOC
< prev
next >
Wrap
Text File
|
1993-01-04
|
154KB
|
4,819 lines
RLIB
Version 2.0
February 18, 1989
Useful Functions for the Clipper Applications Programmer
Copyright 1988, 1989 Richard Low
TABLE OF CONTENTS
-----------------
COPYRIGHT AND TRADEMARK NOTICES . . . . . . . . . . . . . . . . . . 4
DISCLAIMER . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
CONTENTS OF RLIB PACKAGE . . . . . . . . . . . . . . . . . . . . . 6
INTRODUCTION . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
FUNCTION SUMMARY . . . . . . . . . . . . . . . . . . . . . . . . . 9
ALPHABETICAL LISTING . . . . . . . . . . . . . . . . . . . . . . . 10
ABOUT SHAREWARE AND REGISTRATION . . . . . . . . . . . . . . . . . 12
WHAT YOU GET . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
RLIB REGISTRATION FORM . . . . . . . . . . . . . . . . . . . . . . 14
LINKING RLIB INTO YOUR APPLICATION . . . . . . . . . . . . . . . . 15
MODIFYING THE RLIB LIBRARY . . . . . . . . . . . . . . . . . . . . 16
RLIB FUNCTIONS
ALPHADATE() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
ATINSAY() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
BARMENU() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
BEEP() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
BOXASK() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
BOXMENU() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
BRIGHT() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
CENTER() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
CHANGED() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
CLOSEAREA() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
DECRYPTED() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
ENCRYPTED() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
_______________________________________________________________________
RLIB 2.0 2
FILEDATE() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
FILES() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
FILETIME() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
FORGET() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
GETPARM() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
KEYINPUT() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
MARKREC() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
MEMORIZE() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
MREPLACE() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
MULTIMENU() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
NAMESPLIT() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
NTXKEYVAL() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
PARENT() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
PATHTO() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
PDOWNINIT() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
PDOWNMENU() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
PICKFILE() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
PICKREC() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
RJUSTIFY() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
SAYINBOX() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
STR2DATE() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
APPENDIX A
RLIB QUICK REFERENCE . . . . . . . . . . . . . . . . . . . . . 80
_______________________________________________________________________
RLIB 2.0 3
COPYRIGHT AND TRADEMARK NOTICES
-------------------------------
CLIPPER and NANTUCKET are trademarks of Nantucket Corporation.
dBASE, and dBASE III PLUS are trademarks of Ashton-Tate, Inc.
IBM and PC-DOS are trademarks of International Business Machines Corp.
LOTUS and 123 are trademarks of Lotus Development Corporation.
MASM, LIB, MS-DOS, Microsoft, Microsoft Object Linker and Microsoft
Library Manager are trademarks of Microsoft Corporation.
PLINK86 and PLINK86plus are trademarks of Phoenix Technologies, Ltd.
TLINK and Turbo Link are trademarks of Borland International.
CompuServe is a trademark of CompuServe Incorporated.
Any other trademarks of other companies which may appear in this
documentation are for identification purposes only.
_______________________________________________________________________
RLIB 2.0 4
DISCLAIMER
----------
The RLIB function library is provided "as is" without warranty of
any kind, either expressed or implied, including but not limited to the
implied warranties of merchantability and fitness for a particular
purpose. No representation is made that the RLIB functions will meet
the users' particular requirements. The user assumes the entire risk
associated with the use of the RLIB functions and is solely responsible
for the use and operation of these functions in any application the
user distributes which may make use of RLIB functions.
_______________________________________________________________________
RLIB 2.0 5
CONTENTS OF RLIB PACKAGE
------------------------
Filename Size Description
-------- ------ -----------------------------
READ.ME 539 Latest information/changes
CONTENTS.DOC 2,871 Text file listing contents
RLIB.LIB 55,808 The RLIB library
RLIB.DOC 154,155 RLIB Documentation
RLIB.MAK 1,159 RLIB make file
MAKERLIB.BAT 16 Batch file for making the library
MAKEDEMO.BAT 57 Batch file to compile and link the demo
DEMO.DBF 1,186 The demo database
DEMO.DBT 21,504 The associated demo memo file
DEMO.PRG 33,109 The demo program
DEMOPROC.PRG 15,144 Procedures for the demo program
RL_ALPHA.PRG 601 Source code for the ALPHADATE() function
RL_ATINS.PRG 708 Source code for the ATINSAY() function
RL_BARME.PRG 6,683 Source code for the BARMENU() function
RL_BEEP.PRG 726 Source code for the BEEP() function
RL_BOXAS.PRG 4,625 Source code for the BOXASK() function
RL_BOXME.PRG 6,057 Source code for the BOXMENU() function
RL_BRIGH.PRG 892 Source code for the BRIGHT() function
RL_CENTE.PRG 907 Source code for the CENTER() function
RL_CHANG.PRG 1,871 Source code for the CHANGED() function
RL_CLOSE.PRG 1,747 Source code for the CLOSEAREA() function
RL_DECRY.PRG 387 Source code for the DECRYPTED() function
RL_ENCRY.PRG 521 Source code for the ENCRYPTED() function
RL_FILED.PRG 563 Source code for the FILEDATE() function
RL_FILES.PRG 906 Source code for the FILES() function
RL_FILET.PRG 536 Source code for the FILETIME() function
RL_FORGE.PRG 850 Source code for the FORGET() function
RL_GETPA.PRG 1,154 Source code for the GETPARM() function
RL_KEYIN.PRG 2,989 Source code for the KEYINPUT() function
RL_MARKR.PRG 10,611 Source code for the MARKREC() function
RL_MEMOR.PRG 1,761 Source code for the MEMORIZE() function
RL_MREPL.PRG 919 Source code for the MREPLACE() function
RL_MULTI.PRG 13,151 Source code for the MULTIMENU() function
RL_NAMES.PRG 2,459 Source code for the NAMESPLIT() function
RL_NTXKE.PRG 571 Source code for the NTXKEYVAL() function
RL_PAREN.PRG 1,554 Source code for the PARENT() function
RL_PATHT.PRG 1,713 Source code for the PATHTO() function
RL_PDOWN.PRG 15,334 Source code for the PDOWNMENU() function
RL_PICKF.PRG 3,316 Source code for the PICKFILE() function
RL_PICKR.PRG 12,172 Source code for the PICKREC() function
RL_RJUST.PRG 257 Source code for the RJUSTIFY() function
RL_SAYIN.PRG 6,131 Source code for the SAYINBOX() function
RL_STR2D.PRG 1,467 Source code for the STR2DATE() function
_______________________________________________________________________
RLIB 2.0 6
INTRODUCTION
------------
RLIB was designed as a collection of tools for the Clipper
Applications Programmer. Good applications require a solid, consistent
user interface. Creating routines for menus, data entry and editing is
a time consuming process, one we all hope to avoid on a repetitive
basis. So, I have assembled a collection of functions that give a wide
range of applications-oriented use: Menus, Dialogue Boxes, Database
record selection routines, string handling, and much more.
There are several libraries available for Clipper programmers that
provide indispensable functions and procedures. Most of these library
functions are written in C and Assembler and provide access to features
which are not currently supported in Clipper. RLIB was not designed to
provide these types of low level functions, mainly because I am not an
Assembler or C programmer. I am a Clipper programmer, and I create
customized applications programs and systems. Therefore, I was
interested in developing a collection of functions to make this job
faster and above all, consistent.
All of the functions in RLIB are written in the Summer '87 version
of Clipper. All of the routines that RLIB utilizes are contained in
the CLIPPER and EXTEND libraries which are distributed as part of the
Clipper package. Clipper has a rich set of commands and functions
which give programmers many tools to create an almost limitless
collection of procedures, functions, and applications. If you are
curious as to some of the capabilities of Clipper, then check out the
functions in RLIB. They are ALL WRITTEN 100% IN CLIPPER!
One distinction between RLIB and several other Clipper libraries
is that RLIB comes with FULL SOURCE CODE INCLUDED! The source code
offers several benefits. First, you can tailor these functions if you
so desire. You can expand (or limit) the operation of functions to
suit your needs. If a particular function behaves in a way you would
like to change, then all you have to do is change it.
Secondly, I hope that this source code may provide some level of
instruction for those of you who may be starting off with Clipper or
just want to see what Clipper can do. I learned to program in Clipper
the hard way, by making my own mistakes. But I also read every bit of
source code I could get my hands on to see how and what can be done.
As far as the level of instruction these functions may offer, I make no
proclamation to being the best Clipper programmer around. However, I
have been programming and writing applications in Clipper since I
purchased my copy of the Winter '85 version.
Thirdly, you too can create your own libraries of functions. With
the source code comes a complete explanation on how to build a library
of Clipper compiled functions using a library manager.
_______________________________________________________________________
RLIB 2.0 7
So now, fire up Clipper, compile and link the DEMO.PRG program
included with this package, and get a hands on view of RLIB functions.
To easily compile and link DEMO.PRG, just run the MAKEDEMO.BAT compile
and link batch file provided.
Happy Clippering!
_______________________________________________________________________
RLIB 2.0 8
FUNCTION SUMMARY
----------------
To give you a feeling for the range of uses for the functions in
RLIB, I have categorized them for your reference.
MENU SCREEN FILE
-------------- -------------- -------------
BARMENU() ATINSAY() FILEDATE()
BOXMENU() * BOXASK() * FILES()
MULTIMENU() * BRIGHT() FILETIME()
PDOWNMENU() * CENTER() PARENT()
SAYINBOX() * PATHTO()
PICKFILE()
CHARACTER DATABASE MISCELLANEOUS
-------------- -------------- -------------
DECRYPTED() CHANGED() ALPHADATE()
ENCRYPTED() CLOSEAREA() BEEP()
GETPARM() FORGET() NTXKEYVAL()
KEYINPUT() MARKREC() *
NAMESPLIT() * MEMORIZE()
RJUSTIFY() MREPLACE()
STR2DATE() PICKREC() *
Several functions deserve particular attention for their
usefulness. These functions are noted with an asterisk (*) following
the function name above. I consider these to be the 'application
sellers' and I use them all the time, and they are great! PICKREC()
especially is great for designing database add, edit, delete etc.
routines.
The next page consists of a brief description of the purpose of
each function.
_______________________________________________________________________
RLIB 2.0 9
ALPHABETICAL LISTING
--------------------
ALPHADATE() Convert a date variable to date character string.
ATINSAY() At a given screen coordinate SAY an expression IN the
color setting provided.
BARMENU() Create Lotus 123 style light bar menus.
BEEP() Ring the system bell multiple times.
BOXASK() Pop up a dialogue box in the center of the screen to get
user response.
BOXMENU() Create 'boxed' menus with total control!
BRIGHT() Get the bright version of the current or indicated color.
CENTER() Determine the column position to center text on an 80
column display, optionally displaying it.
CHANGED() Determine if field memory variables were changed during
an edit.
CLOSEAREA() Close multiple database work areas with one command.
DECRYPTED() Un-encrypt a character string encrypted with ENCRYPTED().
ENCRYPTED() Encrypt a character string.
FILEDATE() Get the last update date for a file.
FILES() Determine if multiple files exist with one function.
FILETIME() Get the last update time for a file.
FORGET() Release field memory variables created with MEMORIZE().
GETPARM() Retrieve a comma delimited parameter from a character
string.
KEYINPUT() Get keyboard input while echoing dots on the screen.
MARKREC() Select multiple database records to process from a pop-up
selection window.
MEMORIZE() Save all field values to memory variables for edit.
_______________________________________________________________________
RLIB 2.0 10
MREPLACE() Replace database fields with field memory variables
created with MEMORIZE().
MULTIMENU() Create multi-column menus allowing left, right, up, and
down cursor movement to select.
NAMESPLIT() Convert names in the form First Middle Last to Last,
First Middle.
NTXKEYVAL() Get the controlling index key value for the current
record.
PARENT() Get the parent directory name for the current or supplied
directory.
PATHTO() Search the DOS path for the path leading to a given
filename.
PICKFILE() Pop up a file directory listing to pick a file and return
the filename.
PICKREC() Pop up a menu of database records from which to pick a
record.
PULLDOWN() Create "pull down" menus.
RJUSTIFY() Right justify character strings by moving trailing blanks
to the front.
SAYINBOX() Easily display messages in the center of the screen in a
dialogue box.
STR2DATE() Convert dates in the form January 31, 1988 to 01/31/88.
_______________________________________________________________________
RLIB 2.0 11
ABOUT SHAREWARE AND REGISTRATION
--------------------------------
For me, shareware is a wonderful concept. The concept is to allow
easy access to the widest array of software which can be evaluated at
no cost. It is called shareware because it is meant to be shared, or
distributed, by users via floppy disk and/or electronic bulletin boards
so that an ever increasing number of people can obtain access to it.
The person evaluating this software does not have to shell out any
money to try it, unlike most commercial packages. Who wants to lay out
$500.00, $100.00, or even $35.00 just to look at or try software that
may or may not fit your needs? Shareware enables you to try it, and if
you like it, to buy it. It's that simple.. a wonderful idea.
However, this does not mean that shareware is free! If you like
what you have tried, and intend on using it, you should purchase that
software.
I have spent much time and effort creating and documenting these
functions. While the driving force behind this effort is to share what
I think are really useful Clipper functions and to demonstrate that a
myriad of nifty things can be done in Clipper, I am also putting forth
this effort with the prospect of selling the fruits of my labor. So,
if you like these functions, and find them of use and plan on using
them, you need to complete the registration form on the next page and
send it in with your payment of $35.00 to purchase your copy of RLIB.
With your payment you will become a registered user entitling you to
free updates and new releases. Also, registered users are entitled to
free support if you have any questions or problems with any of the RLIB
functions.
Under this shareware concept, please feel free to distribute
copies of RLIB to whomever you wish. The only restrictions are that:
1. You may not distribute RLIB in any modified form, but only in the
original format as received by you. 2. You may not charge any fee for
RLIB or its distribution. 3. You must distribute all files and parts
of RLIB as referenced in this document.
_______________________________________________________________________
RLIB 2.0 12
WHAT YOU GET
------------
When you purchase RLIB, you get unlimited use of the software.
You may compile and link the RLIB functions into your own applications
and distribute these applications without royalties to the author of
RLIB. You may modify the source code to these functions although the
author cannot support any RLIB function whose source code has been
changed.
Basically you get unlimited use of the RLIB functions in both
object code and source code format. Although the RLIB documentation is
copyrighted material, the RLIB functions are not so as not to limit
your ability to freely use them in your applications without having to
worry about royalties.
You also get support. Once you purchase your copy of RLIB, feel
free to contact me regarding any problems you may have with any RLIB
functions. The best way to contact me is through CompuServe, or you
may call me at home. I also welcome any suggestions or comments you
may have.
My home address, address, CompuServe ID and home telephone number
are listed below:
Richard Low
6701 Parkway Road
Baltimore, Maryland 21239
CompuServe ID: 72007,1063
Home telephone: (301) 377-8529
_______________________________________________________________________
RLIB 2.0 13
RLIB REGISTRATION FORM
----------------------
To purchase and register your copy of RLIB please complete the form
below and mail with your check or money order for $35.00 to:
RICHARD LOW
6701 PARKWAY ROAD
BALTIMORE, MARYLAND 21239
Your Full Name: ________________________________________________
Address: ________________________________________________
City: ________________________________________________
State: _______________________
Zip Code: _______________
Home Telephone: (_______)_______________________
Work Telephone: (_______)_______________________
Product: RLIB Version 2.0
_______________________________________________________________________
RLIB 2.0 14
LINKING RLIB INTO YOUR APPLICATION
----------------------------------
To include any RLIB functions in your application, you must
include the RLIB library name in your list of libraries when linking.
The only requirement is that you must include the Clipper EXTEND.LIB
library since RLIB makes use of functions in this library. Also you
MUST list RLIB BEFORE EXTEND.LIB so the linker will properly pick up
the routines. (Apparently linkers do not make a second pass through
the libraries to see if a library that follows one on the list calls a
routine in a preceding one).
The syntax for using PLINK86 would be:
plink86 FILE yourprog LIB clipper,rlib,extend
^
`---------------,
|
|
To use MS-LINK, type: |
|
link yourprog,,,clipper + rlib + extend |
^ |
`----------------------|
|
|
To use TLINK, type: |
|
tlink yourprog,,,clipper + rlib + extend |
^ |
`------------------|
|
|
|
<< YOU MUST LIST RLIB BEFORE EXTEND >>-------'
_______________________________________________________________________
RLIB 2.0 15
MODIFYING THE RLIB LIBRARY
--------------------------
You may want to custom tailor some of the functions in RLIB to meet
your own needs. Since the source code is provided for RLIB, this
capability is what makes RLIB so versatile. All you need is, of
course, a copy of Clipper and a library manager program such as LIB
from Microsoft. Included with this package is an RLIB.MAK "make" file
which can be used to maintain and keep the library up to date. See the
discussion of how to use a library manager in the documentation that
comes with the package you use.
When writing a collection of functions to build into a library, the
biggest difference between Clipper compiled functions and functions
written in other languages is that Clipper uses the filename to
identify the function "symbol". If you have a program named TEST.PRG,
when you compile it with Clipper, you get a TEST.OBJ file. That's ok
if TEST.PRG does something useful, but if all TEST.PRG does is to
contain a function named TEST, then Clipper will give you a SYMBOL
REDEFINITION ERROR. This is because Clipper is trying to create two
symbols for the linker, both with the same name; one named TEST for the
.PRG file (program) itself, the other for the function named TEST
contained in that .PRG file.
For this reason, .PRG files that contain nothing but a function must
have a name different from the function name itself. Therefore, all
the RLIB functions are contained in .PRG files starting with "RL_" and
ending with the first 5 letters of the function name. Of course you
could get around this by having one .PRG file named RLIB.PRG with all
of the functions separately listed within it, but this nullifies the
advantage of using a library. If you did it that way, ALL of the code
would be linked into your application whether you called all the
functions within it or not. Having the functions contained in a
library is handy because only those functions you use are extracted and
included in your .EXE file when linked.
_______________________________________________________________________
RLIB 2.0 16
RLIB FUNCTIONS
==============
The following section contains documentation for each of the RLIB
functions. Each function begins on a separate page and provides the
following information:
Function description
Syntax prototype
Return value
Parameters
Usage
Behavior
Example(s)
Source filename
Cross references
_______________________________________________________________________
RLIB 2.0 17
ALPHADATE()
-----------
This function provides a convenient method of printing a date in the
form January 1, 1988. If you print out text date strings often in your
application, using the following code gets old quick:
CMONTH(date)+' '+LTRIM(STR(DAY(date)))+', '+STR(YEAR(date),4,0)
Syntax:
ALPHADATE( [date] )
Returns:
The specified date (or the system date if no parameter was given)
as a character string in the form: January 1, 1986.
Parameters:
date......... Optional date type variable. If no parameter is
specified, the current system date is returned.
Example:
*-- print the current date as a character string
? 'The current date is: ' + ALPHADATE()
*-- result = The current date is October 6, 1988
*-- print 9/10/87 as a character string
datevar = CTOD('09/10/87')
@ 5,0 SAY ALPHADATE(datevar)
* result = September 10, 1987
Source: RL_ALPHA.PRG
See also: FILEDATE()
_______________________________________________________________________
RLIB 2.0 18
ATINSAY()
---------
This function takes screen coordinates, a color setting, and a string
as parameters, and SAYs the string at the location specified, in the
color setting specified. (AT <coordinates> IN <color> SAY <string>)
Syntax:
ATINSAY( row, column, color, string )
Returns:
Nothing useful.
Parameters:
row.......... Numeric value indicating the row on which to
display <string>. Value must be between 0 and 24.
column....... Numeric value indicating the column position on
which to display <string>. Value must be between 0
and 79.
color........ Character string indicating the color setting to
use in displaying <string>. This character string
must be consistent with Clipper's color setting
requirements. See the Clipper manual under SET
COLOR for details.
string....... The character string to display.
Usage:
This function is useful if you spend a lot of time SETting COLOR
TO and back while @...SAYing messages. See the example for the
code it eliminates.
Behavior:
This function has a 'black box' design in that it preserves the
cursor position and current color setting. Therefore, you can use
it to print strings in different color settings without disrupting
either the color or cursor position.
_______________________________________________________________________
RLIB 2.0 19
Example:
*-- old way of displaying a message in White on Red, then
*-- changing back to White on Black
SET COLOR TO w/r
@ 24,30 SAY 'A sample message on line 24'
SET COLOR TO w/n
*-- new way
ATINSAY( 24, 30, 'w/r', 'A sample message on line 24' )
Source: RL_ATINS.PRG
See also: BOXASK(), CENTER(), KEYINPUT(), RJUSTIFY(), SAYINBOX()
_______________________________________________________________________
RLIB 2.0 20
BARMENU()
---------
BARMENU makes creating horizontal light bar menus a snap. Although
creating this type of menu has been simplified with Clipper's PROMPT
and MENU TO commands, this function offers additional flexibility while
keeping your code to a minimum.
Syntax:
BARMENU( row, options [,columns [,choice [,altkeys [,exitkeys;
[,prompts [,prompt_row [,colors ]]]]]]] )
Returns:
The number of the array element chosen, or zero if the escape key
or an exitkey is pressed (see the discussion of exitkeys below).
Parameters:
row........... Numeric value indicating the row for the bar menu
to appear. Value must be between 0 and 24.
options....... Array of menu options. Specify the array name
without quotes to pass this array by reference.
columns....... Optional array of column numbers for each menu
choice. The column numbers in this array must
match the order for the menu options, and each
value must be between 0 and 79. Specify the array
name without quotes to pass this array by
reference. If omitted, BARMENU() will place two
columns (spaces) between menu options.
choice........ Optional numeric value indicating the starting menu
option number. Value checked to be between 1 and
the number of elements in the option array. If an
out of range value is given, the starting number
will be 1.
altkeys....... Optional character string indicating what keys may
be pressed to select the corresponding menu option.
The default 'direct select keys' are the first
letter of each of the menu options, but if this
string is provided, it is added to that list. The
requirement is that the AT() position of the
character in the alternate key list is the numeric
equivalent of the corresponding menu choice.
_______________________________________________________________________
RLIB 2.0 21
exitkeys...... Optional character string indicating which keys if
pressed will cause an exit and return zero. If
omitted or an empty (or null) string is specified,
then the Escape Key will default to being the only
key to cause a 'return zero exit'. If this
parameter is specified as a logical .F., then no
keys will cause a return 0 exit (it will be
disabled), and only the Enter Key or a direct
select key will cause an exit condition.
prompts....... Optional array of prompt messages corresponding to
each of the menu options. Specify the array name
without quotes to pass the array by reference.
prompt_row.... Optional numeric value indicating the row for the
optional prompt messages to appear. This value
must be between 0 and 24. The default is row 24.
colors........ Optional array of character strings specifying the
color settings to use. The colors used for the
different parts of the menu are specified as
follows:
colors[1] = Menu choices.
colors[2] = Menu selection bar.
colors[3] = <not used by BARMENU()>
colors[4] = Menu bar line background.
colors[5] = Selected choice on exit.
If you use this color feature, DECLARE your colors
array to have at least 5 elements. If the colors
option is not specified or there are less than 5
elements, then the default colors are used. These
defaults are: the current Standard color is used
for bar and item displays, and the Enhanced color
is used for the menu bar.
Usage:
Used to build the horizontal light bar menus that are common in
many applications today.
Behavior:
In addition to the right and left arrow keys, the space bar and
back space keys move the menu bar to the right and left. The menu
bar line background (color[4]) is used to clear the menu line and
place it in that color. Like all RLIB functions, if an optional
parameter is omitted, but one of the following parameters is used,
you must pass a 'dummy' parameter in the place of the omitted
parameter. The best 'dummy' to use is a null string ('').
_______________________________________________________________________
RLIB 2.0 22
Example:
*-- present menu choices in a 123 style menu
*-- declare arrays for menu and message options
DECLARE option[5], prompt[5]
*-- menu choices
option[1] = 'File'
option[2] = 'Edit'
option[3] = 'Next'
option[4] = 'Previous'
option[5] = 'Quit'
*-- corresponding message prompts
prompt[1] = 'Load, Save, Transfer, Erase, Quit'
prompt[2] = 'New orders, Repairs, Exchanges, Quit'
prompt[3] = 'Skip to the next entry'
prompt[4] = 'Skip to the previous entry'
prompt[5] = 'Quit and return to DOS'
*-- set up column position numbers so options fill across screen
*-- File Edit Next Previous Quit
*-- if omitted options will look like this:
*-- File Edit Next Previous Quit
column[1] = 0
column[2] = 18
column[3] = 36
column[4] = 54
column[5] = 76
*-- let the down and up arrows also select Next and Previous
*-- the AT() position of altkeys in the string must match the
*-- corresponding array element number.
altkeys = 'FE' + CHR(24) + CHR(5) + 'Q'
*-- set up colors to be used
DECLARE colors[5]
colors[1] = 'B/BG' && options are Blue on Cyan
colors[2] = 'B/W' && menu bar is Blue on White
colors[3] = '' && not used
colors[4] = 'B/BG' && menu line also Blue on Cyan
colors[5] = 'W+/BG' && selected option Bright White
*-- keep Escape from causing exit, force them to press Q
allowexit = .F.
_______________________________________________________________________
RLIB 2.0 23
*-- initial choice = 'File' = 1
choice = 1
*-- display menu on row 1 with messages on row 2
choice = BARMENU( 1, column, option, choice, altkeys,;
allowexit, prompts, 2, colors )
Source: RL_BARME.PRG
See also: BOXMENU(), MULTIMENU(), PDOWNMENU()
_______________________________________________________________________
RLIB 2.0 24
BEEP()
------
This function merely rings the system bell the specified number of
times. It is useful in replacing the sequence ?? CHR(7) + CHR(7) +
CHR(7) with BEEP(3). (I admit, it's not very sophisticated, but I use
it all the time!)
Syntax:
BEEP( [number] )
Returns:
Nothing useful, it just rings the bell. However, if you must
know, the return value is a null ('')
Parameters:
number........ Optional numeric variable specifying the number of
times to ring the bell. If no parameter is
specified, the bell will be sounded one time.
Example:
*-- ring the bell
BEEP()
*-- ring it 10 times
BEEP(10)
Source: RL_BEEP.PRG
See also: No relatives.
_______________________________________________________________________
RLIB 2.0 25
BOXASK()
--------
BOXASK presents a painless way to pop up a dialogue box in the center
of the screen to ask for a keypress response. The intended use is for
displaying error messages of some sort while usually asking if they
want to continue. Up to nine lines may be included with the color used
for the box being optional.
Syntax:
BOXASK( [color,] line1 [,line2 .... ,line9] [,timeout] )
Returns:
The character pressed or a null string ("") if timed out.
Parameters:
color......... Optional variable or constant indicating the screen
color setting to use in the form required by
Clipper (e.g. 'W/N'). If omitted, the current
color setting is used.
line1......... Character string to be displayed within the box.
The string may be up to 65 characters long.
line2..9...... Optional additional lines to be displayed. Up to
nine lines may be included, each up to 65
characters in length.
timeout....... Optional numeric value indicating the number of
seconds to wait for a response before "timing out"
and returning a null string. If omitted, the
default wait time is forever.
Behavior:
The character that is returned is converted to upper case (if it
is between 'a' and 'z'). BOXASK() is capable of returning any
ASCII character even control characters, the character returned
will be the CHR() equivalent of the INKEY() pressed.
This is one of the few functions that breaks the rule that says,
if you want to skip a parameter, you must pass a dummy in its
place. In this function, the first parameter is evaluated to
determine if it is a string to be displayed in the box, or if it
_______________________________________________________________________
RLIB 2.0 26
is a color setting. The first parameter is deemed to be a color
setting if the 2nd, 3rd, or 4th character is the '/' character.
At least one line must be specified, if the character string is
longer than 65 characters, it is truncated. If the optional
timeout parameter is specified the message will remain on screen
for that many seconds or until any key is pressed then disappear.
This is useful for displaying messages for several seconds without
having to require the user to press a key.
The following defaults apply to determine how the box is
positioned in the middle of the screen:
Centering - The box is centered on screen from top to
bottom, and left to right depending on the
number of lines and the widest line. One blank
line is placed above and below the first and
last line to be displayed, and five spaces are
placed in front of and trailing the widest line
to be displayed. Each line is centered within
the box.
Environment - The previous screen underneath the box, the
current color setting, and the cursor position
are saved and restored on exit (after a
keypress). In other words, the box disappears
and you are left where you were.
Example:
*-- during a memory save, warn user of existing file and ask if
*-- they want to overwrite it, and wait one minute for a response
IF FILE('config.mem')
line1 = '*** WARNING ***'
line2 = 'The file CONFIG.MEM already exists!'
line3 = 'Overwrite it? (Y/N)'
*-- use a warning color Yellow on Red and wait 60 seconds
IF BOXASK('GR+/R', line1, line2, line3, 60 ) = 'Y'
SAVE TO config.mem ALL LIKE cfg_*
ENDIF
ENDIF
Source: RL_BOXAS.PRG
See also: SAYINBOX()
_______________________________________________________________________
RLIB 2.0 27
BOXMENU()
---------
BOXMENU combines the usefulness of Clipper's ACHOICE() function and
MENU TO command to give you a convenient way to pop up menus in a box.
Some of the features of BOXMENU are: automatic highlighting of the
selected option, automatic 'dulling' of the menu box when finished, and
multiple valid 'option' strings to allow not only the first letter of
the options to be picked, but a list of option letters you pass as a
parameter.
Syntax:
BOXMENU( row, column, options [, choice [, altkeys [, exitkeys;
[, prompts [, prompt_row [, colors ]]]]]] )
Returns:
The number of the array element chosen, or zero if the escape key
or an exitkey is pressed (see the discussion of exitkeys below).
Parameters:
row.......... Numeric value indicating the row for the top left
corner of the menu box. Value must be between 0
and 24.
column....... Numeric value indicating the column for the top
left corner of the menu box. The value must be
between 0 and 79.
options...... Array of menu options. Specify the array name
without quotes to pass this array by reference.
choice....... Numeric value indicating the starting menu option
number. Value checked to be between 1 and the
number of elements in the option array. If an out
of range value is given, the starting number will
be 1.
altkeys...... Optional character string indicating what keys may
be pressed to select the corresponding menu option.
The default 'direct select keys' is the first
letter of each of the menu options, but if this
string is provided, it is added to that the list.
The requirement is that the AT() position of the
character in the alternate key list is the numeric
equivalent of the corresponding menu choice.
_______________________________________________________________________
RLIB 2.0 28
exitkeys..... Optional character string indicating which keys if
pressed will cause an exit and return zero. If
omitted or an empty (or null) string is specified,
then the Escape Key will default to being the only
key to cause a return zero exit. If this parameter
is specified as a logical .F., then no keys will
cause a return 0 exit (it will be disabled), and
only the Enter Key will cause an exit condition.
prompts...... Optional array of prompt messages corresponding to
each of the menu options. Specify the array name
without quotes to pass the array by reference.
prompt_row... Optional numeric value indicating the row for the
optional prompt messages to appear. This value
must be between 0 and 24. The default is row 24.
colors....... Optional array of character strings specifying the
color settings to use. The colors used for the
different parts of the menu are specified as
follows:
colors[1] = Menu choices.
colors[2] = Menu selection bar.
colors[3] = Active menu box color (on entry).
colors[4] = Inactive menu box color (on exit).
colors[5] = Selected choice on exit.
If you use this color feature, DECLARE your colors
array to have at least 5 elements. If the colors
option is not specified or there are less than 5
elements, then the default colors are used. These
defaults are: the current Standard color is used
for the box and item displays, and the Enhanced
color is used for the menu bar.
Behavior:
BOXMENU() follows a popular and logical sequence for producing box
style menus. The active menu is surrounded by a double line box.
When it becomes inactive after a choice is made, the box border
changes to a single line to indicate the menu is no longer active.
If the row and or column positions supplied are out of bounds (not
between 0 and 24, and 0 and 79) a default row or column of 1 will
be used. Also, since this is mainly a menuing tool, no provision
has been made to scroll menu items below the bottom of the menu
box. Consequently, you should consider how many options will be
in the menu when determining the top row, as the bottom of the box
is calculated by adding the number of options in the array. If
more elements exist in the array than will fit in the box,
unpredictable screen displays will occur. This exclusion was made
for the benefit of speed and compactness of code. If a scrollable
menu is needed, use ACHOICE().
_______________________________________________________________________
RLIB 2.0 29
Example:
*-- declare arrays for menu and message options
DECLARE option[5], message[5]
*-- menu choices
option[1] = " 1. Add new records (Append) "
option[2] = " 2. Edit records (Change) "
option[3] = " 3. Delete records (Remove) "
option[4] = " 4. Update records (Modify) "
option[5] = " 5. Quit and return (eXit) "
*-- corresponding messages
message[1] = "Add new records to the database"
message[2] = "Edit records already in the database"
message[3] = "Delete selected records"
message[4] = "Update dates of last appointments"
message[5] = "Leave this menu and return to previous"
*-- in addition to pressing 1,2,3,4, or 5, (default select keys)
*-- let the following keys also select the choices
alt_keys = 'AEDUQ' + 'ACRMX'
DECLARE colors[5]
colors[1] = 'N/BG' && options are Black on Cyan
colors[2] = 'W+/GR' && menu bar is Bright White on Brown
colors[3] = 'R+/BG' && active menu is Bright Red on Cyan
colors[4] = 'R/BG' && in-active is Red on Cyan
colors[5] = 'R/BG' && selected choice is Red on Cyan
*-- allow Escape and Left and Right arrow keys to exit
exit_keys = CHR(27) + CHR(19) + CHR(4)
*-- start with first choice
choice = 1
*-- put up menu on row 2, column 10, with messages on row 24
choice = BOXMENU( 2, 10, option, choice, alt_keys, exit_keys,;
message, 24, colors )
Source: RL_BOXME.PRG
See also: BARMENU(), MULTUMENU(), PDOWNMENU()
_______________________________________________________________________
RLIB 2.0 30
BRIGHT()
--------
This function returns the bright color attribute setting for either the
current color, or the optionally supplied color parameter. This is
useful for switching around color combinations without having to
clutter up your code with all that SUBSTR(SUBSTR(... garbage.
Syntax:
BRIGHT( [color] )
Returns:
A character string indicating the bright color setting. The same
as extracting the standard part of the color setting and adding a
'+' onto the foreground part.
Parameters:
color........ Optional character string indicating the color
setting from which to extract the bright portion.
If omitted, the current color setting (returned by
SETCOLOR()) is used.
Behavior:
If the standard color setting foreground is white, then BRIGHT()
makes the high intensity color Yellow (GR+) instead of bright
white. I personally consider this a better interpretation than
'bright brown', which is what yellow is.
Example:
*-- save incoming color, then get bright portion
save_color = SETCOLOR(BRIGHT())
CENTER(10,'*** TRY AGAIN ***') && see CENTER()
SETCOLOR(save_color) && restore old color
Source: RL_BRIGH.PRG
See also: GETPARM()
_______________________________________________________________________
RLIB 2.0 31
CENTER()
--------
Almost everyone has a function to center text on the screen. So why
should RLIB have one also? This does just what you think; it takes the
string provided, and returns the numeric column position to center the
text on an 80 column display. Only this center can also do the
displaying, which helps cut down on wordy code. See the example below.
Syntax:
CENTER( [ row, ] string )
Returns:
Numeric integer value of the column number to center <string> on
an 80 column display monitor.
Parameters:
row.......... Optional numeric value which, if passed, will cause
CENTER to print <string> centered on row number
<row>. Value checked to be between 0 and 24.
string....... Target character string used to determine center
position, and optionally, to print on row number
<row> if <row> is given as a parameter.
Example:
*-- this method requires two lines of code and a memvar
memvar = 'This is the string to center on row 23'
@ 23,CENTER(memvar) SAY memvar
*-- or without assigning string to memvar (very wordy)
@ 23,CENTER('This is the string to center on row 23') ;
SAY 'This is the string to center on row 23'
*-- the simpler way
CENTER(23,'This is the string to center on row 23')
Source: RL_CENTE.PRG
See also: ATINSAY()
_______________________________________________________________________
RLIB 2.0 32
CHANGED()
---------
CHANGED is designed to serve as a replacement for the Clipper UPDATED()
function when used in conjunction with the MEMORIZE() function. It may
also be used to compare the contents of all fields in a record to
previously MEMORIZED() copies to determine if changes have been made to
the record since it was MEMORIZED(). Changed tests to see if memory
field variables have been changed from the associated field values
after an edit. This works better than Clipper's UPDATED() function
because once you test for UPDATED(), the flag is cleared. So if you go
back and READ the data again, in a loop for instance, but do NOT change
anything this second time around, UPDATED() will return .F., even
though something was changed previously. Ideally, when testing for
UPDATED() you want it to be .T. if any values have changed since the
last replace.
CHANGED() must be used in conjunction with MEMORIZE(), MREPLACE(), and
FORGET() functions. These functions take all the fields in the current
database, and store the field values to memory variables of the same
name, prefaced by M->.
Syntax:
CHANGED()
Returns:
True (.T.) if any changes made to field variables since the last
replace or MEMORIZE().
Parameters:
None
Example:
*-- this way will not trap an update on re-read
DO WHILE .T.
*-- get data
@ 1,0 GET M->name
@ 2,0 GET M->city
@ 3,0 GET M->state
READ
*-- if changed, this will be true, however, after going back
*-- through the second time, UPDATED() will only be true if
*-- another change was made. Pressing Escape the second
_______________________________________________________________________
RLIB 2.0 33
*-- time will not be trapped as UPDATED() will be False.
IF UPDATED()
IF LASTKEY() = 27 && escape key
@ 0,60 SAY "Abort edit? (Y/N)"
answer = INKEY(0)
@ 0,60 SAY SPACE(20)
IF .NOT. answer $ "Yy"
LOOP
ENDIF
ENDIF
ENDIF
*-- CHANGED() will compare all M->memvars with the twin
*-- field name to see if any values are different.
ENDDO
*-- this way will work
*-- save all database field data to field variables
MEMORIZE()
DO WHILE .T.
*-- get data (remember to preface memvars with M->)
@ 1,0 GET M->name
@ 2,0 GET M->city
@ 3,0 GET M->state
READ
*-- changed will catch it no matter how many times
*-- you go back through the loop
IF CHANGED()
IF LASTKEY() = 27 && escape key
@ 0,60 SAY "Abort edit? (Y/N)"
answer = INKEY(0)
@ 0,60 SAY SPACE(20)
IF .NOT. answer $ "Yy"
LOOP
ENDIF
ENDIF
ENDIF
ENDDO
Source: RL_CHANG.PRG
See also: MEMORIZE(), MREPLACE(), FORGET()
_______________________________________________________________________
RLIB 2.0 34
CLOSEAREA()
-----------
CLOSEAREA allows you to close up to nine database files at one time
with one line of code without having to leave the currently selected
work area. This is useful when you have several database files open
and you want to close all but one or two of them.
Syntax:
CLOSEAREA( [ work_area, work_area ... ] )
Returns:
True (.T.) if all went as expected, False (.F.) if an error.
Parameters:
work_area.... Number or Alias name of the work area to close. If
this parameter is a number, it must be a valid
select area number. If the parameter is an Alias
name, it must be the correct alias as a character
string. If no parameters are specified, the
current work area is closed.
Usage:
Select area numbers and work area Alias names may be intermixed as
parameters. Up to nine areas may be specified. If no parameter
is given, this will be the same as issuing the USE command,
closing the current area.
Behavior:
CLOSEAREA steps through the work areas specified and issues a USE
command to close the database. After all is finished, control is
returned to the selected work area at entry. A return value of
.F. should only occur if an invalid parameter is passed (i.e. a
Date, Memo, or Logical type parameter) or if you specify an alias
name that does not exist. Normally an invalid alias name will
trigger a TYPE MISMATCH runtime error, so CLOSEAREA tests any
alias names for proper existence.
Example:
If you had seven databases open and wanted to close all but the
_______________________________________________________________________
RLIB 2.0 35
databases in work areas 1 and 3 (aliases SALES and CUSTOMERS), one
of the ways to accomplish this task would be with the following
code:
SELECT 1
marker1 = RECNO()
SELECT 3
marker3 = RECNO()
CLOSE DATABASES
SELECT 1
USE Sales INDEX Sales ALIAS Sales
GOTO marker1
SELECT 3
USE Cust INDEX Cust ALIAS Customers
GOTO marker3
Another way to do this would be as follows:
SELECT 2 && Invoices
USE
SELECT 4 && Payments
USE
SELECT 5 && Payables
USE
SELECT 6 && Inventory
USE
SELECT 7 && Ledger
USE
With CLOSEAREA(), the following is a LOT easier and simpler!!!
CLOSEAREA(2,4,5,6,7)
or:
CLOSEAREA( 2, 'Payments', 'Payables', 'Inventory', 'Ledger' )
Source: RL_CLOSE.PRG
See also: No relatives.
_______________________________________________________________________
RLIB 2.0 36
DECRYPTED()
-----------
The is the companion to the ENCRYPTED function that follows and is used
to Decrypt strings so encrypted. See discussion below for ENCRYPTED().
Syntax:
DECRYPTED( string )
Returns:
An un-encrypted version of <string> of identical length.
Parameters:
string....... The character string to decrypt.
Behavior:
Strings decrypted with this function must have been encrypted with
the companion ENCRYPT function.
Example:
*-- check a password stored in encrypted format
@ 5,0 SAY 'Enter your password:'
*-- allow only 40 characters, upper case, and echo dots
password = KEYINPUT( 40, .T., .F. ) && see KEYINPUT()
USE system.dbf
IF .NOT. password == DECRYPTED(pword)
SAYINBOX( 'W/R', '*** ACCESS DENIED! ***', 6 )
USE
RETURN
ENDIF
Source: RL_DECRY.PRG
See also: ENCRYPTED(), KEYINPUT(), SAYINBOX()
_______________________________________________________________________
RLIB 2.0 37
ENCRYPTED()
-----------
The are several Encrypt/Decrypt functions out there, most of which are
written in assembly or C. This is a simple Encryption scheme done
entirely in Clipper which is not only functional, but the source is
easily altered to provide unique algorithms. Data encrypted with this
function is Decrypted with the companion DECRYPTED function.
Syntax:
ENCRYPTED( string )
Returns:
An encrypted version of <string> of identical length.
Parameters:
string....... The character string to encrypt.
Behavior:
Strings encrypted with this function can only be decrypted with
the DECRYPT function, or with an authentic World War II decoder
machine.
Example:
*-- get password, then store in encrypted format
@ 5,0 SAY 'Enter your password:'
*-- allow only 40 characters, upper case, and echo only dots
password = KEYINPUT( 40, .T., .F. ) && see KEYINPUT()
USE system.dbf
REPLACE pword WITH ENCRYPTED(password)
Source: RL_ENCRY.PRG
See also: DECRYPTED()
_______________________________________________________________________
RLIB 2.0 38
FILEDATE()
----------
This function extracts the date from the given file's directory entry
information. It is useful for comparing the dates of two files, or for
using the file date for a variety of purposes. I have used it in
conjunction with FILETIME() to determine if an index file is current
with the associated .DBF file. FILEDATE() simplifies all the ADIR()
and associated lines of code to get the file date.
Syntax:
FILEDATE( filename )
Returns:
Date from the file's directory entry (last update date).
Parameters:
filename..... Character string or variable indicating the name of
the file for which to extract the date. This
filename (filespec) must and may adhere to any
fully qualified filename as required by ADIR().
Usage:
If an invalid filename is given, or if the file does not exist,
FILEDATE() will return an empty date ( / / ). Beware that if
the file being checked is currently open, the date from the
directory entry may not reflect updates until the file is closed.
Example 1:
*-- see if the date and time of the .DBF and .NTX files agree
ok = ( FILEDATE('myfile.dbf') == FILEDATE('myfile.ntx') .AND.;
FILETIME('myfile.dbf') == FILETIME('myfile.ntx') )
USE myfile INDEX myfile
IF .NOT. ok
? 'Please wait, updating index...'
REINDEX
GO TOP
ENDIF
Example 2:
_______________________________________________________________________
RLIB 2.0 39
*-- prompt user for file backup request
lastback = FILEDATE('myfile.bak')
? 'MYFILE.DBF was last backed up on ' + ALPHADATE(lastback)
WAIT 'Do you want to back it up now? (Y/N)' TO answer
IF answer $ 'Yy'
ERASE myfile.bak
COPY FILE myfile.dbf TO myfile.bak
ENDIF
Source: RL_FILED.PRG
See also: FILETIME(), FILES()
_______________________________________________________________________
RLIB 2.0 40
FILES()
-------
This function tests for the existence of multiple files at one time.
It is useful for reducing a wordy FILE() concoctenation.
Syntax:
FILES( filename [, filename...filename ] )
Returns:
True if all the specified files exist.
Parameters:
filename...... Character string or variable of the file to test
for existence. Up to nine filenames may be given,
separated by commas.
Usage:
Used in place of a series of FILE() functions .AND.ed together.
If you have to test for more than one file often, this really
cleans things up and makes code very readable.
Behavior:
FILES() uses the Clipper FILE() function to successively test for
each file specified. If any test fails, FILES() returns False.
Since the FILE() function is used, it follows Clippers current SET
DEFAULT setting.
Example:
*-- see if all needed index files exist
USE Sales
IF FILES( "Custno.ntx", "Invoice.ntx",;
"Salesman.ntx", "Repair.ntx",;
"Saledate.ntx" )
SET INDEX TO Custno, Invoice, Salesman, Repair, Saledate
ELSE
*-- do indexing
ENDIF
_______________________________________________________________________
RLIB 2.0 41
*-- the old way to do it
IF FILE("Custno.ntx" ) .AND. FILE("Invoice.ntx") .AND.;
FILE("Salesman.ntx") .AND. FILE("Repair.ntx" ) .AND.;
FILE("Saledate.ntx")
Source: RL_FILES.PRG
See also: FILEDATE(), FILETIME()
_______________________________________________________________________
RLIB 2.0 42
FILETIME()
----------
This function extracts the time from the given file's directory entry
information. It is useful for comparing the times of two files, or for
using the file time for a variety of purposes. See the discussion of
the associated FILEDATE() function.
Syntax:
FILETIME( filename )
Returns:
Time from the file's directory entry as a character string in the
form HH:MM:SS (last update time).
Parameters:
filename..... Character string or variable indicating the name of
the file for which to extract the time. This
filename (filespec) must and may adhere to any
fully qualified filename as required by ADIR().
Usage:
If an invalid filename is given, or if the file does not exist,
FILETIME() will return a null string (''). Beware that if the
file being checked is currently open, the directory time may not
reflect updates until the file is closed.
Example:
See examples above for FILEDATE().
Source: RL_FILET.PRG
See also: FILEDATE(), FILES()
_______________________________________________________________________
RLIB 2.0 43
FORGET()
--------
This function is designed to be used in conjunction with CHANGED(),
MEMORIZE(), and MREPLACE(); they are all a team. Put together, they
simplify the tedious task of making a memory variable copy of each
field in a database record to work with (some languages call them
temporary field variables), and then replacing the fields with the
associated memory copy after edits. FORGET() is used to release the
PUBLIC variables created by MEMORIZE() when your editing is finished.
Syntax:
FORGET()
Returns:
True (.T.) if all fields successively released.
Parameters:
None.
Usage:
Since variables created with MEMORIZE() are declared PUBLIC,
FORGET() releases them to reclaim memory and to avoid any
potential name conflicts. Some programmers save all field values
to memory variables with a common prefix (like x_), and when they
are finished with them do a RELEASE ALL LIKE x_*. This is fine if
the variables are released in the same procedure in which they
were created. However, it is more efficient to do this storing in
a sub-procedure, hence the need to make these variables PUBLIC.
The problem is that in Clipper, you cannot RELEASE ALL LIKE x_* if
the x_* variables are PUBLIC variables that were created in
another procedure. FORGET() takes care of all this by explicitly
naming each variable to be RELEASEd, which is the only way you can
release a PUBLIC variable created in another procedure.
Example: See examples for MEMORIZE(), CHANGED(), and REPLACED().
Source: RL_FORGE.PRG
See also: CHANGED(), MEMORIZE(), MREPLACE()
_______________________________________________________________________
RLIB 2.0 44
GETPARM()
---------
This function is used to retrieve a comma delimited parameter from a
character string. The ways in which this can be used are unlimited,
but as an example, several RLIB functions use GETPARM() to retrieve
color settings from the strings provided.
Syntax:
GETPARM( position, string )
Returns:
Character string equal to the parameter.
Parameters:
position...... Numeric value indicating the ordinal position in
the parameter list.
string........ The comma delimited string from which to extract
the characters following the <position>-1 comma.
Usage:
Used RLIB to parse the SETCOLOR() color string for default colors
when no color arrays are specified in the functions that offer
color as an option. (You must therefore not remove GETPARM() from
RLIB!)
Behavior:
If there exists no characters at the ordinal position indicated,
GETPARM() returns a null string.
Example:
*-- supply your UDF with several parameters all bunched in
*-- one character string
files = 'TEST1.DBF, TEST2.DBF, TEST3.DBF, TEST4.DBF, TEST5.DBF'
*-- this UDF opens all the files in your string
*-- in separate work areas
OPENFILES(files)
_______________________________________________________________________
RLIB 2.0 45
.
.
.
*-- now here's your UDF to open many files in one swoop
FUNCTION OPENFILES
PARAMETERS filenames
PRIVATE file2open
DO WHILE .T.
file2open = GETPARM( x, filenames )
IF EMPTY(file2open)
EXIT
ENDIF
SELECT 0
USE &file2open
ENDDO
RETURN .T.
Example #2:
*-- get the current Enhanced color setting
mreverse = GETPARM( 2, SETCOLOR() )
Source: RL_GETPA.PRG
See also: BRIGHT()
_______________________________________________________________________
RLIB 2.0 46
KEYINPUT()
----------
There is no built in way of allowing key input while echoing dots on
the screen to prevent on-lookers from seeing what is being entered.
SETting COLOR TO X will blank out the screen but then you cannot see
how many characters have been entered. We may want to see dots echo
(as most BBS' do) so we can tell how many characters we have entered.
With keyinput you can easily do this, while also determining the
maximum length of the input string, whether or not it is to be all
upper case, and whether or not to echo the actual characters on the
screen, or just dots. Key input starts accepting character input at
the current cursor location on the screen and terminates when either
the maximum character count has been reached or ENTER is pressed.
Syntax:
KEYINPUT( length, upper_case, echo_chars )
Returns:
The character string typed in, or a null string ('') if the Escape
key was pressed.
Parameters:
length....... Numeric value specifying the maximum allowable
length of the string that may be entered (and
returned by KEYINPUT). If this value is greater
than the remaining width of the screen, key input
will wrap to the next line.
upper_case... Logical value (.T./.F.) indicating if all
characters inputted will be forced into upper case.
The default is false, characters will be returned
as entered.
echo_chars... Logical value (.T./.F.) indicating if inputted
characters will appear on the screen. If this
value is false, dots will echo on screen. The
default is true, characters will echo on screen.
Example:
*-- get the user's password, keep it less than or equal to 30
*-- characters, make it upper case, and echo dots on the screen
_______________________________________________________________________
RLIB 2.0 47
@ 5,0 SAY 'Enter your password: '
password = KEYINPUT( 30, .T., .F. )
Source: RL_KEYIN.PRG
See also: NAMESPLIT()
_______________________________________________________________________
RLIB 2.0 48
MARKREC()
---------
MARKREC() lets a user select multiple records from a database to be
included in some subsequent operation. One such use is for prompting
the user for records to include in a report. They cursor up and down
through a menu consisting of field expressions, and press a designated
mark key to select the record. When the user terminates by pressing
the Enter key, MARKREC() returns a list of record numbers or field
contents of the records selected.
Syntax:
MARKREC( top, left, bottom, right, output [, markkey
[, markfield [, colors ] ] ] )
Returns:
A character string consisting of selected "markfield" data, or the
default of selected record numbers, each eight digits long,
delimited with a comma ",", or a null string if Escape was
pressed.
Parameters:
top........... Numeric values specifying the window coordinates
left.......... of the 'display box'. The top and bottom values
bottom........ must be between 0 and 24, and the left and right
right......... coordinates must be between 0 and 79.
output........ Character expression which evaluates to a field
list to be displayed at runtime. This value is
used as a macro substitution, so it must evaluate
correctly to a character string.
markkey....... Optional numeric value indicating which key will
act as the 'marker' key. This value is equal to
the ASCII INKEY() value of the key. If omitted or
an invalid parameter is supplied, the default value
is -8 which is the INKEY() value for the F9 key.
markfield..... The field name (or expression) as a character
string, indicating the data to be extracted and
placed into the "pick list". This field or
expression must evaluate to a character string. If
no parameter is supplied, or an invalid parameter
(such as a dummy), the default markfield is the
record number as an 8 digit character string.
_______________________________________________________________________
RLIB 2.0 49
colors........ Optional array of character strings specifying the
color settings to use.
colors[1] = Standard color for un-marked records
colors[2] = Standard color for marked records
colors[3] = Highlite color for un-marked records
colors[4] = Highlite color for marked records
If you use this color feature, DECLARE your colors
array to have at least 4 elements. If the colors
option is not specified or there are less than 4
elements, then the default colors are used. These
defaults are:
colors[1] = Standard color setting
colors[2] = Bright standard color
colors[3] = Enhanced color setting
colors[4] = Blinking enhanced color
Behavior:
MARKREC() behaves very similar to PICKREC() except instead if
picking one record, you mark several records for processing.
MARKREC() skips forward and backward through the database records
as the up and down arrow keys are pressed. The PgUp and PgDn
scroll one window full of records. When the Enter key is pressed,
MARKREC() exits and returns a list of selected records in the form
of a string of record numbers, each 8 digits with a comma
delimiter. For example, if the marked records were record numbers
5, 12 and 123, the string would be: " 5, 12, 123,".
Notice the trailing comma, as a comma is added to the end of each
selected record number. To process the selected records you may
use either FOR...$ logic, or a loop to extract each record number
to process. See the examples. If the markfield parameter is
supplied, this field (or expression) is extracted, and a trailing
comma added to the end. You can create your parsing loop based on
the length of this field or expression.
If the field list expression display is wider that the width of
the display box, it is truncated; if it is shorter, spaces are
added onto the end to make the selection bar as wide as the box.
Examples:
*-- database of customer orders, select orders to print
*-- Orderno and Customer are fields in your database
output = "Orderno + ' ' + Customer"
*-- draw a double line box with a title header
@ 1,0,22,36 BOX ' '
_______________________________________________________________________
RLIB 2.0 50
@ 2,0 SAY ' CUSTOMER ORDERS '
@ 3,0 SAY ' '
marked = MARKREC( 4, 2, 21, 35, output, -4 )
*-- now could print information in one of two ways
*-- #1
REPORT FORM custrepo FOR STR(RECNO(),8,0)+"," $ marked
*-- the comma on the end solves the problem of a mistaken
*-- match from two record numbers concatenated together
*-- " 110000000" = record 1 and 10000000, but would
*-- match on record number 11 or 110 or 1100 etc...
*-- method number 2 is quicker but more code
DO WHILE LEN(marked) > 0
*-- get a record number from list (1st 8 digits in list)
mrecord = VAL(SUBSTR(marked,1,8))
GOTO mrecord
DO <report printing routine>
*-- strip off first 9 characters (8 digits plus a comma)
marked = SUBSTR(marked,10)
ENDDO
Source: RL_MARKR.PRG
See also: PICKREC()
_______________________________________________________________________
RLIB 2.0 51
MEMORIZE()
----------
This function is designed to be used in conjunction with the CHANGED(),
MREPLACE(), and FORGET() functions; they are all a team. Put together,
they simplify the 'scattering and gathering' of database field contents
into and from associated memory variables (some languages call them
temporary field variables). What MEMORIZE() does is to create a PUBLIC
memory variable with the same name as each of the fields in the current
record of the currently selected database file, and assigns to that
memory variable the value of its associated field. You then GET the
contents of the memory variable rather than GETting the field directly.
After your READ is finished, you check to see if any of the memory
variable values have CHANGED() from their database field counterparts
and, if so, issue a MREPLACE() then FORGET() them. The process may
seem a little complicated at first, but it's a lot easier than
cluttering up code with STORE TO's and REPLACE WITH's.
Syntax:
MEMORIZE( [ blank ] )
Returns:
True (.T.) if all fields successively stored to memory variables.
Parameters:
blank......... Optional LOGICAL (.T.|.F.) which if given and is
True tells MEMORIZE() to create a empty M->memvar
of the associated field type for each database
record field.
Usage:
Used to store a working copy of all the database record field
contents to memory variables for editing. This is good
programming practice in that you should never GET a field
directly, but only work with a copy which can later be REPLACed.
The 'blank' option is useful for creating a set of field variables
when appending a new record. Remember, memory variables created
with MEMORIZE() have the same name as their database field
counterparts. Whenever there are fields and memory variables with
the same names, fields take precedence. So to access these
variables you must preface the variable name with the memory
variable identifier alias M->.
_______________________________________________________________________
RLIB 2.0 52
Behavior:
Each memory variable created is the same data type as its
associated field. If the optional blank parameter is supplied,
each of these variables are empty (Memo field variables are
initialized as a character string of zero length). The following
table of samples gives the data types created:
FIELD NAME FIELD TYPE LENGTH VARIABLE NAME BLANK VALUE
---------- ---------- ------ ------------- ----------------
Name Character 32 M->name SPACE(32)
BirthDate Date 8 M->birthdate CTOD(' / / ')
Age Numeric 2 M->age 0
Male Logical 1 M->male .F.
Comments Memo 10 M->comments ''
Example:
*-- store empty field values for a new record
MEMORIZE(.T.)
*-- get the data
@ 1,0 SAY 'Enter full name' GET M->name
@ 2,0 SAY 'Enter birthdate' GET M->birthdate
@ 3,0 SAY 'Enter age ' GET M->age PICTURE '##'
*-- remember to always PICTURE numeric memory variables
READ
*-- now add the new record and put in the data
APPEND BLANK
MREPLACE()
*-- now release the public variables
FORGET()
Source: RL_MEMOR.PRG
See also: CHANGED(), MREPLACE(), FORGET()
_______________________________________________________________________
RLIB 2.0 53
MREPLACE()
----------
This functions is designed to be used in conjunction with MEMORIZE(),
CHANGED(), and FORGET() functions; they are all a team. Put together,
they simplify the 'scattering and gathering' of database field contents
into and from associated memory variables (some languages call them
temporary field variables). What MREPLACE() does is to replace each
field in the current database record with the associated field memory
variable that was created with MEMORIZE() and, usually, recently
edited.
Syntax:
MREPLACE()
Returns:
True (.T.) if all fields successively replace.
Parameters:
None.
Behavior:
Memory variables created with MEMORIZE() have the same name as
their database field counterparts. Whenever there are fields and
memory variables with the same names, fields take precedence. So
to access these variables you must preface the variable/field name
with the memory variable identifier alias M->. MREPLACE() does a
REPLACE <field> WITH <fieldvar> for each field of the database
record.
Example:
*-- store field values
MEMORIZE()
*-- get the data
@ 1,0 SAY 'Enter full name' GET M->name
@ 2,0 SAY 'Enter city name' GET M->city
@ 3,0 SAY 'Enter the State' GET M->state
@ 4,0 SAY 'Enter the zip ' GET M->zip
READ
_______________________________________________________________________
RLIB 2.0 54
*-- if changed, update the record, otherwise why bother
IF CHANGED()
IF .NOT. MREPLACE()
SAYINBOX('Error writing fields! Replace failed.')
ENDIF
ENDIF
*-- now release the public variables
FORGET()
Source: RL_MREPL.PRG
See also: CHANGED(), FORGET(), MEMORIZE()
_______________________________________________________________________
RLIB 2.0 55
MULTIMENU()
-----------
MULTIMENU is a Multi-column menu selection function. Many programs
offer a list of options to choose from displayed across the screen,
allowing you to cursor up, down, left and right to navigate around the
options. This function takes an array of character strings and
displays them in this format.
Syntax:
MULTIMENU( top, left, bottom, right, options [, columns ;
[, messages [, message_row [, colors ] ] ] ] )
Returns:
The number of the array element chosen, or zero if the escape key
is pressed.
Parameters:
top.......... Numeric values specifying the window coordinates
left......... of the 'display box'. The top and bottom values
bottom....... must be between 0 and 24, and the left and right
right........ coordinates must be between 0 and 79.
options...... Array of options. Specify the array name without
quotes to pass this array by reference.
columns...... Optional numeric value indicating the number of
columns to use for displaying the options. If this
parameter is omitted, or a non numeric data type is
passed, or if it is zero, the columns will be
calculated to fit the most options across the
'window' boundaries.
messages..... Optional array of messages corresponding to each of
the options. Specify the array name without quotes
to pass the array by reference.
message_row.. Optional numeric value indicating the row for the
optional messages to appear. This value must be
between 0 and 24. The default is row 24.
colors....... Optional array of character strings specifying the
color settings to use. The colors used for the
different parts of the menu are specified as
follows:
_______________________________________________________________________
RLIB 2.0 56
colors[1] = Menu choices.
colors[2] = Menu selection bar.
colors[3] = <not used>
colors[4] = <not used>
colors[5] = Selected choice on exit.
If you use this color feature, DECLARE your colors
array to have at least 5 elements. If the colors
option is not specified or there are less than 5
elements, then the default colors are used. These
defaults are: the current Standard color is used
for the item displays, and the Enhanced color is
used for the menu selection bar.
Behavior:
If any of the first four parameters specifying the window
coordinates are out of bounds, or the <right> is less than or
equal to <left>, or <bottom> is less than or equal to <top>,
MULTIMENU will bomb out and return zero. Also, if the options
array is empty, a zero will be returned. If the number of columns
option is omitted (or zero to make the number of columns
automatic), MULTIMENU will position columns so that columns are
separated by at least one space. If more elements exist in the
array than will fit in the display window given the number of
columns being used, the PgDn and PgUp keys will skip forward and
back between windows.
Example:
*-- display fields in box with structure for each shown below
USE manyflds.dbf
*-- declare arrays for field names
num = FCOUNT()
DECLARE fields[num], types[num], widths[num], dec[num]
DECLARE struct[num]
AFIELDS( fields, types, widths, dec ) && fill with .DBF info
FOR x = 1 TO num
*-- now make each field name 12 spaces wide
fields[x] = STRETCH(fields[x],12)
*-- and build field description for each
struct[x] = IF( types[x] = 'C', 'Character',;
IF( types[x] = 'N', 'Numeric',;
IF( types[x] = 'L', 'Logical',;
IF( types[x] = 'D', 'Date', 'Memo')))) +;
' Length: ' + STR(widths[x],3,0) +;
' Decimals: ' + STR(dec[x],3,0)
NEXT x
_______________________________________________________________________
RLIB 2.0 57
*-- now present these fields in a single line box
@ 1,0,10,79 BOX ' '
*-- present fields with structure for each on line 11
*-- the zero makes UDF calc column number dynamically
fieldnum = MULTIMENU( 2,1,9,78, fields, 0, struct, 11 )
Source: RL_MULTI.PRG
See also: BARMENU(), BOXMENU()
_______________________________________________________________________
RLIB 2.0 58
NAMESPLIT()
-----------
This function is useful for parsing names to split up into the lastname
firstname components. What NAMESPLIT does is let you type in a name in
the form RICHARD LOW, and it returns LOW, RICHARD. This is
particularly useful for SEEKing names from an index that was indexed on
PAD(TRIM(Lastname) + ', ' + Firstname, 32). Such an index will insure
correct ordering of names.
Syntax:
NAMESPLIT( name )
Returns:
A character string equal to name flipped to Lastname first, with a
comma space inserted.
Parameters:
name......... Character string indicating the string to parse
into Lastname, Firstname.
Behavior:
NAMESPLIT is aware of the standard name suffixes, i.e. JR. SR. II,
2ND, III, 3RD, 4TH, M.D., PHD, and will make recognize these as
not being lastnames. Without this, a name entered as RICHARD C.
LOW, JR. may incorrectly be split into JR., RICHARD C
Example:
*-- file is indexed on: PAD( TRIM(Lastname)+", "+Firstname, 32 )
ACCEPT 'Enter name to locate:' TO mname
*-- they enter "RICHARD LOW"
SEEK NAMESPLIT(mname)
*-- it finds "LOW, RICHARD"
Source: RL_NAMES.PRG
See also: KEYINPUT()
_______________________________________________________________________
RLIB 2.0 59
NTXKEYVAL()
-----------
This function allows you to easily get the value of an index key field
from the currently selected database. It is handy in place of using
the INDEXKEY() function and subsequent macro substitution.
Syntax:
NTXKEYVAL()
Returns:
The value of the current database index key, of a type determined
by the type of field in the index key expression.
Parameters:
None.
Behavior:
If no database file is open, or no index file is open, NTXKEYVAL()
returns a null string ("").
Example:
*-- save the index key value for comparison
savekey = NTXKEYVAL()
*-- do whatever you want to do
.
.
*-- see if an index key field was changed in the process
IF savekey != NTXKEYVAL()
*-- do corrective things
ENDIF
Source: RL_NTXKE.PRG
See also: PICKREC()
_______________________________________________________________________
RLIB 2.0 60
PARENT()
--------
This function returns the name of the parent directory to either the
current directory, or to the optionally supplied directory.
Syntax:
PARENT( [directory] )
Returns:
A character string indicating the name of the parent directory
(i.e. the directory above).
Parameters:
directory..... Optional name of the directory whose parent
directory you wish to find.
Usage:
This can be useful in directory/file management routines when you
want to let a user navigate through the directory structure.
Although you can get the names of sub-directories with ADIR(), if
you want to take them 'back up' a directory, you have to get the
current directory name, and strip it down to find the parent
directory part. PARENT() makes this task easy.
Behavior:
If the current or supplied directory is at the top level (i.e. the
root directory), PARENT() will return '\'.
Example:
*-- current directory is \APPS\CLIPPER\TEST
? PARENT() && returns '\APPS\CLIPPER'
? PARENT('C:\DOS\UTILITY') && returns 'C:\DOS'
Source: RL_PAREN.PRG
See also: PATHTO()
_______________________________________________________________________
RLIB 2.0 61
PATHTO()
--------
This function searches the current DOS path to find the path pointing
to the indicated file. This is usually used to build a fully qualified
filename ('d:[path]filename') as a character string to be used to open
a file. In the example below, a help file is kept in the same drive
and directory as the program (.EXE) file. The path to the .EXE file is
found and used to point to the help file. This way, the help file can
be located at runtime, provided the directory it is in is in the path.
Syntax:
PATHTO( filename )
Returns:
A character string indicating the path pointing to <filename> plus
a trailing backslash '\'. If the file is not found along the DOS
path, then a null string ('') is returned.
Parameters:
filename..... The name of the file to find through the path.
Example:
*-- Example program name is DEMO.EXE, and help file is named
*-- DEMO.HLP and both are located in C:\MYAPPS.
*-- path=C:\;C:\DOS;C:\CLIPPER;C:\UTILITY;C:\MYAPPS
PROCEDURE Help
PARAMETERS a,b,c && remember to get parms
helppath = PATHTO('demo.exe') && returns 'C:\MYAPPS\'
helpfile = helppath + 'DEMO.HLP' && 'C:\MYAPPS\DEMO.HLP'
IF FILE(helpfile)
USE &helpfile
<help code>
ENDIF
RETURN
Source: RL_PATHT.PRG
See also: PARENT()
_______________________________________________________________________
RLIB 2.0 62
PDOWNINIT()
-----------
To initialize the PDOWNMENU() function. This call is required to set
up the variables used to control PDOWNMENU(). Since PDOWNMENU() has a
lot of work to do, it is inefficient to repeat many of the processes
each time the function is called. Therefore, I split it up into an
initialization routine, and the menuing routine.
Syntax:
PDOWNINIT( [ row, columns, menus, items, startnums [,prompts ;
[,promptrow [,colors [,altkeys [,exit ]]]]] ] )
Returns:
True if initialization was successful, false otherwise.
Parameters:
row........... Numeric value indicating the row for the pull down
menus to appear. Value must be between 0 and 24.
columns....... Array of column numbers indicating the left corner
position for each of the pull down menus. The
column numbers must be between 0 and 79, and the
left column of a given menu must be less than 79 -
the width of the menu, or erratic screen painting
errors will occur.
menus......... Array of top level menu choices. These are the
menu options that appear across the top (on row) in
a manner similar to BARMENU().
items......... Array of pull down menu items. There must be at
least one element for each option of each menu.
These are the options that 'fill' each of the pull-
down boxed menus.
startnums..... Array element numbers indicating at which element
number each set of menu options start within the
items array. There should be one element for each
corresponding menu.
prompts....... Optional array of messages which correspond to each
of the menu items. There should be one element for
each corresponding item.
_______________________________________________________________________
RLIB 2.0 63
promptrow..... Optional numeric row on which these prompts will
appear.
colors........ Optional ARRAY of colors to use for the top Bar and
pull down Box menus.
color[1] - Option & message displays
color[2] - Menu selection bars
color[3] - Pull-down menu box ACTIVE color
color[4] - Pull-down menu box IN-ACTIVE color
color[5] - Pull-down menu option after selection
color[6] - Menu bar option after selection
If omitted, the default colors for the menus are:
color[1] - Current Standard color.
color[2] - Current Enhanced color.
color[3] - Bright (BRIGHT()) Standard color.
color[4] - Current Standard color.
color[5] - Bright (BRIGHT()) Standard color.
color[6] - Bright (BRIGHT()) Standard color.
altkeys....... Optional array of character strings indicating the
alternate select keys for each of the pull-down
menu choices. There should be one element for each
corresponding menu. If omitted, the default direct
select keys is the first letter of each menu item.
exit.......... Optional logical value indicating if the ESCAPE key
will cause an exit from the top level menu. If
omitted, the default is false.
Usage:
PDOWNINIT() establishes the working environment for PDOWNMENU(),
things such as the column coordinates, underlying screen, menu
colors, alternate select keys etc.. If this information had to be
re-passed to PDOWNMENU() on each call (many times in a menu
control loop) then the parameter passing and parameter parsing
overhead would slow PDOWNMENU() unnecessarily.
Behavior:
Upon initialization, a PUBLIC array is established to hold various
environment information. This array is named RL_PD[], so check
that this name does not conflict with any others in your program.
To release this public array, and clear the PDOWNMENU environment,
issue the PDOWNINIT() function with no parameters. Although not
absolutely necessary, it is probably a good idea to release
variables and arrays that are not being used.
_______________________________________________________________________
RLIB 2.0 64
Examples:
*-- arrays to hold top menu, columns, and starting elements
DECLARE menus[5], columns[5], starts[5]
menus[1] = 'File'
menus[2] = 'Edit'
menus[3] = 'View'
menus[4] = 'Utility'
menus[5] = 'Quit'
columns[1] = 0
columns[2] = 24
columns[3] = 41
columns[4] = 58
columns[5] = 76
*-- declare array to hold items in each menu
DECLARE items[14]
starts[1] = 1
items[ 1] = 'Retrieve '
items[ 2] = 'Save '
items[ 3] = 'Erase '
starts[2] = 4
items[ 4] = 'Record '
items[ 5] = 'File '
items[ 6] = 'Memo '
starts[3] = 7
items[ 7] = 'Record '
items[ 8] = 'File '
items[ 9] = 'Memo '
starts[4] = 10
items[10] = 'Directory '
items[11] = 'Reccount '
items[12] = 'Index '
starts[5] = 13
items[13] = 'No '
items[14] = 'Yes '
*-- initialize Pull Down menu on row 1 using default colors & keys
CLEAR
PDOWNINIT( 1, columns, menus, items, starts )
Source: RL_PDOWN.PRG
See also: BARMENU(), BOXMENU(), MULTIMENU(), PDOWNMENU()
_______________________________________________________________________
RLIB 2.0 65
PDOWNMENU()
-----------
To perform the pull down menuing function after having been initialized
with the PDOWNINIT() function.
Syntax:
PDOWNMENU( @menu, @item, menus, items, columns, startnums;
[, prompts [, exit ] ] )
Returns:
A numeric value equal to the item selected (from the items array)
or zero if escaped pressed (and allowed). Also, since <menu> and
<item> are passed by reference, <menu> will equal the
corresponding menu number, and <item> the item number as it
appears in the menu, starting at 1.
Parameters:
@menu......... This must be a numeric variable which is passed by
reference by preceding it with the '@' symbol.
This allows PDOWNMENU() to change the value of this
variable so your program can act on its value.
@item......... As with @menu, this must be a numeric variable
which is passed by reference by preceding it with
the '@' symbol. This allows PDOWNMENU() to change
the value of this variable so your program can act
on its value.
menus......... Array of top level menu choices.
items......... Array of pull down menu items. There must be one
element for each option of each menu.
columns....... Array of column numbers indicating the left corner
position for each of the pull down menus. The
column numbers must be between 0 and 79, and the
left column of a given menu must be less than 79 -
the width of the menu, or erratic screen painting
errors will occur.
startnums..... Array element numbers indicating at which element
number each set of menu options start within the
items array.
_______________________________________________________________________
RLIB 2.0 66
prompts....... Optional array of messages which correspond to each
of the menu items. There should be one element for
each corresponding item.
exit.......... Optional logical value indicating if the ESCAPE key
will cause an exit from the top level menu. If
omitted, the default is false.
Usage:
Used to create 'pull down' menus seen in so many applications
these days.
Behavior:
The pull down menu consists of two parts: the 'top' level menu
which looks and acts like BARMENU(), and the 'pulled down' menus,
which look and act like BOXMENU()s. When the menu starts, the
left and right arrow keys move the selection bar across the top
menu selection the different menu options. When either the ENTER
key, or the first letter of one of the menu selections is pressed,
the menu drops down to the pull down menu. At this point, the up
and down arrow keys highlite the different menu options, and the
ENTER key or first letter selects each one. The left and right
arrow keys at this point cause PDOWNMENU() to skip from pull down
menu to pull down menu.
Examples:
*-- after having been initialized (see above), do the menu
menu = 1 && start on menu number 1
choice = 0 && do not "pull down" on entry
DO WHILE menu < 5 && #5 = Quit
PDOWNMENU( @menu, @choice, menus, items, columns, starts )
DO CASE
CASE menu = 1 && File
DO fileproc WITH choice
CASE menu = 2 && Edit
DO editproc WITH choice
CASE menu = 3 && View
DO viewproc WITH choice
CASE menu = 4 && Utility
DO utilproc WITH choice
ENDCASE
ENDDO
RETURN
_______________________________________________________________________
RLIB 2.0 67
PROCEDURE fileproc
PARAMETER choice
DO CASE
CASE choice = 1
DO retrieve
CASE choice = 2
DO save
CASE choice = 3
DO erase
ENDCASE
RETURN
Source: RL_PDOWN.PRG
See also: BARMENU(), BOXMENU(), MULTIMENU()
_______________________________________________________________________
RLIB 2.0 68
PICKFILE()
----------
To display a boxed file directory listing from which to choose a file.
This functions allows you to easily build pop-up file listings when you
need to prompt a user for a filename.
Syntax:
PICKFILE( [ filespec [, top, left, bottom [, colors;
[, expanded ] ] ] ] )
Returns:
The selected filename as a character string, or a null string ('')
if the Escape key is pressed.
Parameters:
filespec...... Optional filespec to use for the directory search.
This filespec must follow the conventions required
by ADIR(). If omitted, PICKFILE() defaults to all
files (*.*).
top........... Optional numeric value indicating the top row for
the directory box. If omitted or an invalid
(dummy) parameter is specified, the default row is
row number 6, to center the box on the screen. If
these coordinate parameters are used, all three
must be specified, otherwise the defaults take
hold.
left.......... Optional numeric value indicating the left column
for the directory box. If omitted or an invalid
(dummy) parameter is specified, the default is the
column position necessary to center the directory
box on the screen.
bottom........ Numeric value indicating the bottom row for the
directory box. If omitted or an invalid (dummy)
parameter is specified, the default row is row
number 19, to center the box on the screen.
colors........ Optional character string specifying the color
settings to use. This color setting is passed to
ACHOICE() so the format is that required by
ACHOICE().
_______________________________________________________________________
RLIB 2.0 69
expanded...... Optional logical (true|false) value indicating if
the file listing display is expanded to include
file size, date, and time. The default is true.
Usage:
Useful for popping up file selection menus when a user is required
to enter a filename for a file that already exists on disk.
Behavior:
After the file selection is made, the menu box disappears and the
screen below it is restored. As with all RLIB functions (except
where noted) if you want to skip a parameter, you must pass a
'dummy' parameter in the place of the one you want to skip. The
best dummy parameter is a null string ('').
Example:
*-- ask user for name of .DBF file to USE
*-- make the F10 key the pop-up controller
SET KEY -9 TO FileLister
*-- allocate plenty of space for fully qualified filename
dbf_file = SPACE(60)
@ 10,0 SAY 'Enter filename or press F10 for a list';
GET dbf_file PICTURE '@!S40'
READ
*-- strip off the '.DBF' extension
dbf_file = SUBSTR( dbf_file, 1, AT('.',dbf_file)-1 )
USE &dbf_file
<now do whatever>
* Procedure: FileLister
* Notes....: Procedure to pop-up list of .DBF files. Remember
* to declare parameters in all SET KEY TO procedures.
PROCEDURE FileLister
PARAMETERS callproc, callline, inputvar
&inputvar = PAD( PICKFILE('*.DBF'), LEN(&inputvar) )
RETURN
Source: RL_PICKF.PRG
See also: BOXMENU(), PARENT(), PICKREC()
_______________________________________________________________________
RLIB 2.0 70
PICKREC()
---------
This function provides an easy method of PICKing a RECord from the
currently selected database. One of the most functional uses is for
producing pop-up listings in windows for on line help, or for supplying
a menu of database records from which to select for editing, appending
or deleting. You simply give the function the four screen coordinates
defining the 'display box', and the field list or expression to
display, and it lists these expressions in a box for you to cursor up
and down through to find the one you want and select it by pressing
ENTER. Other parameters allow you to call a procedure to perform
display duties each time the arrow keys are pressed, and facilities for
controlling the display refresh.
Syntax:
PICKREC( top, left, bottom, right, fieldlist, [, procname;
[, condition [, rownumber ] ] ] )
Returns:
Numeric value indicating the current row number (relative to the
top of the 'display box') or zero if the Escape Key was pressed.
This return value is used in loops so that, upon return, PICKREC
will know where it left off. See the description of the
row_number parameter and the example.
Parameters:
top........... Numeric values specifying the window coordinates
left.......... of the 'display box'. The top and bottom values
bottom........ must be between 0 and 24, and the left and right
right......... coordinates must be between 0 and 79.
fieldlist..... Character expression which evaluates to a field
list to be displayed at runtime. This value is
used as a macro substitution, so it must evaluate
correctly to a character string. (Any valid
expression may be used.)
procname...... Optional character string indicating the name of
the procedure to call after each keypress. Care
must be taken to declare this procedure as EXTERNAL
unless you compile and link it in separately as it
is called via macro substitution. If this
parameter is to be skipped, you must pass a 'dummy'
parameter, usually a null string.
_______________________________________________________________________
RLIB 2.0 71
condition..... Optional character string indicating the condition
that records must meet to be included in the list.
This character string is evaluated at runtime via
macro substitution, therefore it MUST evaluate to a
logical expression!
rownumber..... Numeric value indicating the current row number of
the 'selection bar' relative to the top of the
display box. This parameter is required to allow
the function to 'remember' where the bar was upon
return from a previous selection. Additionally,
this parameter allows display refresh control by
optionally passing the following values:
0 - Clear display box, GO to TOP of the
selected database or to the first record
meeting <condition> if specified, and
display records until box filled, End Of
File, or <condition> is false. Zero is
the value passed at startup.
-1 - Clear display box, display records
starting at the current record until box
filled, End Of File or .NOT. &condition.
Usage:
PICKREC is mainly used as an interface for selecting a record from
the currently selected (and FILTERed) database in order to perform
some other action. In the example below, PICKREC acts as the
means for selecting records to edit, and also for adding and
deleting records by pressing the Insert and Delete keys.
Behavior:
PICKREC skips forward and backward through the database records as
the up and down arrow keys are pressed. The PgUp and PgDn scroll
one window full of records. When the Enter key is pressed,
PICKREC exits with the record pointer positioned at the selected
record. If the Escape Key is pressed, the record pointer is at
the last displayed record, but PICKREC returns zero.
If the optional <condition> parameter is used, this character
string MUST evaluate to a logical expression. For example, to
list all sales orders for customer code RCL100, the condition
would be "ALIAS->CUSTNO = 'RCL100'". Notice that strings enclosed
in quotes are bounded by 'quotes within quotes'. If this
condition does not evaluate to a logical expression, a runtime
TYPE MISMATCH error will occur.
_______________________________________________________________________
RLIB 2.0 72
When using conditions, it is important to position the record
pointer to the first record meeting this condition before first
calling PICKREC. PICKREC cannot assume any index files are open
and therefore cannot find the first logical record short of doing
a LOCATE FOR.. command. Since this would be prohibitively slow,
PICKREC assumes the record pointer is at the first logical record
upon entry (with rownumber = 0). Upon re-entry with rownumber
being less than zero, PICKREC will SKIP BACKWARD to find the first
logical record meeting <condition>.
PICKREC uses the current color setting for display of the records
in the window. The color used for the selection bar is the
Enhanced setting, which is the same color used for active GETs.
After selection of a record, that selection is displayed in bright
standard color (the standard color with a '+' placed after the
color letter).
If the field list expression display is wider that the width of
the display box, it is truncated; if it is shorter, spaces are
added onto the end to make the selection bar as wide as the box.
Example #1:
*-- set up a memvar for holding the row number and set it to 0
rownum = 0
*-- PICKREC assumes you are in the desired work area
SELECT Fonebook
*-- allow the Insert and Delete keys to force an exit
keys = CHR(22) + CHR(7)
*-- establish a character string of what you want displayed
*-- this will look like ==> LOW, RICHARD C. - (301) 377-8529
string = "Lastname + ', ' + Firstname + ' - ' + Fonenumber"
*-- draw a double line box with a title header
@ 4,40,23,79 BOX ' '
@ 5,41 SAY ' AVAILABLE PHONE LISTINGS '
@ 6,40 SAY ' '
DO WHILE .T.
*-- now present records from database to choose from
rownum = PICKREC( 7, 41, 22, 78, string, rownum, "", keys )
DO CASE
CASE rownum = 0 && Escape returns 0
EXIT
CASE LASTKEY() = 22 && Insert Key - add a record
MEMORIZE(.T.) && Initialize empty structure
DO edit_proc && perform edits on new entry
rownum = -1 && must force screen refresh with -1
_______________________________________________________________________
RLIB 2.0 73
CASE LASTKEY() = 7 && Delete Key
IF BOXASK('W/R','Are you sure? (Y/N)') = 'Y'
DELETE
rownum = 0 && start over at top of file
ENDIF
CASE LASTKEY() = 13 && Enter Key - edit record
*-- get controlling index key expression if any
ntx_key = NTXKEYVAL()
DO edit_proc
*-- now see if edits changed an index key value
IF .NOT. ntx_key == NTXKEYVAL()
*-- field contents changed from before edits
*-- must refresh screen so order is in sync
rownum = -1
ENDIF
ENDCASE
ENDDO
Example #2:
*-- use PICKREC() to provide pop-up help in field edits
SET KEY -1 TO PopUpHelp && F2 key is pop-up help
mzip = SPACE(5)
@ 10,0 SAY 'Enter zip code (press F2 for listing)';
GET mzip PICTURE '#####'
READ
.
.
.
.
PROCEDURE PopUpHelp
PARAMETERS callproc, linenum, inputvar
PRIVATE inarea
inarea = SELECT()
SELECT ZipCodes
@ 1,50,20,79 BOX double
@ 2,50 SAY ' ZIP CODE LISTING '
@ 4,50 SAY ' ZIP - CITY '
@ 5,50 SAY ' '
_______________________________________________________________________
RLIB 2.0 74
IF PICKREC( 6, 51, 19, 78, "Zip + ' - ' + City" ) > 0
mzip = ZIPCODES->ZipCode
ENDIF
SELECT (inarea)
RETURN
Source: RL_PICKR.PRG
See also: MULTIMENU(), PICKFILE()
_______________________________________________________________________
RLIB 2.0 75
RJUSTIFY()
----------
Takes a character string and moves any trailing blanks to the front of
the string, to allow for right justification in display or printing.
Syntax:
RJUSTIFY( string )
Returns:
String with trailing blanks moved to the front of the string.
Parameters:
string........ Character string or variable to be right justified.
Usage:
Useful for displaying or printing character data that may have
trailing blanks flush right in reports.
Behavior:
The string returned is the same length as the one provided.
Example:
acct_num = SPACE(20)
@ 1,0 SAY 'Enter account number:' GET acct_num
READ
*-- they entered 12-34-567890 which has 8 trailing spaces
*-- you want it printed flush right under the page number
*-- on an 80 column display
@ 1,67 SAY 'Page No.: ' + STR(pageno,3,0)
@ 1,60 SAY RJUSTIFY(acct_num)
*-- replaces: @ 1,60+20-LEN(TRIM(acct_num)) SAY ...
Source: RL_RJUST.PRG
See also: CENTER(), SAYINBOX()
_______________________________________________________________________
RLIB 2.0 76
SAYINBOX()
----------
This is similar to the BOXASK() function, but instead of waiting for a
keypress response like BOXASK(), SAYINBOX() merely puts the message up
on the screen. Where a BOXASK() message disappears when a key is hit,
SAYINBOX() messages stay (with one exception mentioned below). Up to
nine lines may be included, with the color used for the box being
optional.
Syntax:
SAYINBOX( [ color, ] line1 [, line2...line9 ] [ timeout ] )
Returns:
Nothing.
Parameters:
color........ Optional variable or constant indicating the screen
color setting to use in the form 'W/N'. The
default color is WHITE foreground on RED
background.
line1........ Character string to be displayed within the box.
The string may be up to 65 characters long.
line2..9..... Optional additional lines to be displayed. Up to
nine lines may be included.
timeout...... Optional numeric parameter indicating the number of
seconds to pause and leave the message on screen.
Usage:
An easy way to 'pop up' messages in the middle of the screen.
Behavior:
Like BOXASK(), this is one of the few functions that breaks the
rule that says, if you want to skip a parameter, you must pass a
dummy in its place. In this function, the first parameter is
evaluated to determine if it is a string to be displayed in the
box, or if it is a color setting. The first parameter is deemed
to be a color setting if the 2nd, 3rd, or 4th character is the '/'
_______________________________________________________________________
RLIB 2.0 77
character. At least one line must be specified, if the character
string is longer than 65 characters, it is truncated. If the
optional timeout parameter is specified, the message will remain
on screen for that many seconds, or until any key is pressed, then
disappear. This is useful for displaying error or warning
messages for several seconds without having to require the user to
press a key.
The following defaults apply to determine how the box is
positioned in the middle of the screen:
Centering - The box is centered on screen from top to
bottom, and left to right depending on the
number of lines and the widest line. One blank
line is placed above and below the first and
last line to be displayed, and five spaces are
placed in front of and trailing the widest line
to be displayed. Each line is centered within
the box.
Environment - The screen below the box, the current color
setting, and the cursor position are saved and
restored on exit if the optional timeout is
specified. In other words, the box disappears
and you are left where you were.
Examples:
*-- if an index search fails, notify the user and wait 6 seconds
SEEK mname
IF .NOT. FOUND()
line1 = 'No records found under ' + mname
line2 = 'Search terminated!'
*-- use a warning color Bright White on Brown
SAYINBOX( 'W+/GR', line1, line2, 6 )
LOOP
ENDIF
Source: RL_SAYIN.PRG
See also: BOXASK()
_______________________________________________________________________
RLIB 2.0 78
STR2DATE()
----------
To convert a date string in the form of either Jan 1, 1987 or January
1, 1987 to a date type variable.
Syntax:
STR2DATE( datestring )
Returns:
A date variable corresponding to the date supplied in the string.
If the string is in an invalid format, an empty date (' / / ')
is returned.
Parameters:
datestring.... The date string to be converted. String must be in
the form 'Jan 1, 1987' or 'January 31, 1987'.
Usage:
Several software packages store dates in the character string
format Sep 10, 1987. This function is useful for parsing these
strings when importing data and translating into a date type
field.
Example:
*-- get data from import text file from other software
APPEND FROM textfile DELIMITED
*-- date string is in field named StringDate
*-- convert date in form Sep 10, 1988 to date variable
REPLACE Startdate WITH STR2DATE(Stringdate)
Source: RL_STR2D.PRG
See also: ALPHADATE()
_______________________________________________________________________
RLIB 2.0 79
APPENDIX A
RLIB QUICK REFERENCE
====================
ALPHADATE( [date] )
Convert a date variable to date character string.
ATINSAY( row, column, color, string )
At a given screen coordinate SAY an expression IN the color
setting provided.
BARMENU( row, options [,columns [,choice [,altkeys [,exitkeys;
[,prompts [,prompt_row [,colors ]]]]]] )
Create Lotus 123 style light bar menus.
BEEP( [number] )
Ring the system bell multiple times.
BOXASK( [color,] line1 [,line2 .... ,line9] [,timeout] )
Pop up a dialogue box in the center of the screen to get
user response.
BOXMENU( row, column, options [, choice [, altkeys [, exitkeys;
[, prompts [, prompt_row [, colors ]]]]]] )
Create 'boxed' menus with total control!
BRIGHT( [color] )
Get the bright version of the current or indicated color.
CENTER( [ row, ] string )
Determine the column position to center text on an 80 column
display, optionally displaying it.
CHANGED()
Determine if field memory variables were changed during an
edit.
CLOSEAREA( [ work_area, work_area ... ] )
Close multiple database work areas with one command.
_______________________________________________________________________
RLIB 2.0 80
DECRYPTED( string )
Un-encrypt a character string encrypted with ENCRYPTED().
ENCRYPTED( string )
Encrypt a character string.
FILEDATE( filename )
Get the last update date for a file.
FILES( filename [, filename...filename ] )
Determine if multiple files exist with one function.
FILETIME( filename )
Get the last update time for a file.
FORGET()
Release field memory variables created with MEMORIZE().
GETPARM( position, string )
Retrieve a comma delimited parameter from a character
string.
KEYINPUT( length, upper_case, echo_chars )
Get keyboard input while echoing dots on the screen.
MARKREC( top, left, bottom, right, output [, markkey
[, markfield [,colors ] ] ] )
Select multiple database records to process from a pop-up
selection window.
MEMORIZE( [ blank ] )
Save all field values to memory variables for edit.
MREPLACE()
Replace database fields with field memory variables created
with MEMORIZE().
MULTIMENU( top, left, bottom, right, options [, columns ;
[, messages [, message_row [, colors ] ] ] ] )
Create multi-column menus allowing left, right, up, and down
cursor movement to select.
_______________________________________________________________________
RLIB 2.0 81
NAMESPLIT( name )
Convert names from First Middle Last to Last, First Middle.
NTXKEYVAL()
Get the controlling index key value for the current record.
PARENT( [directory] )
Get the parent directory name for the current or supplied
directory.
PATHTO( filename )
Search the DOS path for the path leading to a given
filename.
PDOWNINIT( [ row, columns, menus, items, startnums [,prompts ;
[,promptrow [,colors [,altkeys [,exit ]]]]] ] )
Initialize for PDOWNMENU().
PDOWNMENU( @menu, @item, menus, items, columns, startnums;
[, prompts [, exit ] ] )
Create 'Pull Down' menus.
PICKFILE( [ filespec [, top, left, bottom [, colors;
[, expanded ] ] ] ] )
Pop up a file directory listing to pick a file and return
the filename.
PICKREC( top, left, bottom, right, fieldlist, [, procname;
[, condition [, rownumber ] ] ] )
Pop up a menu of database records from which to pick a
record.
RJUSTIFY( string )
Right justify character strings by moving trailing blanks to
the front.
SAYINBOX( [ color, ] line1 [, line2...line9 ] [ timeout ] )
Display messages in center of the screen in a dialogue box.
STR2DATE( datestring )
Convert dates in the form January 31, 1988 to 01/31/88.
_______________________________________________________________________
RLIB 2.0 82